/**
 * Polyline模块 - 负责地图折线的创建、管理和交互
 * 提供折线批量创建、事件绑定和实例管理功能
 */
import { InfoWindowOptions } from "../InfoWindow/types/index";
import { coordinateConverter } from "../../utils/coordinateConverter";
import { StartingPointSvg, EndPointSvg, StopoverPointSvg, DrivingSvg, PointSvg } from "./images/svg";
import PointPng from "./images/point.png";
import {
  PolylineModule,
  PolylineInstance,
  PolylineMethods,
  AnimationEvent,
  PolylineOptions,
  ExtraOptions,
  PointIcon,
  LngLat,
  LabeledPosition
} from "./types/index";

export default {
  name: "Polyline",
  AMap: null as any,
  map: null as any,

  // 存储所有创建的折线实例
  polylineInstances: [] as PolylineInstance[],

  /**
   * 初始化方法 - 批量创建并添加折线到地图
   * @param {PolylineOptions[]} polylineOptions - 折线配置数组
   * @param {ExtraOptions} [extra={}] - 额外配置选项
   * @returns {Promise<{name: string, instance: PolylineInstance[], events: {remove: () => void, closeInfoWindow: () => void}}>}
   * @throws {TypeError} 当参数不是数组时抛出警告
   */

  // 额外配置
  extra: null as ExtraOptions | null,
  // 折线行进进度
  percent: 0,
  async init(polylineOptions: PolylineOptions[], extra: ExtraOptions = {}): Promise<PolylineModule> {
    if (!this.AMap) {
      return Promise.reject(new TypeError("初始化地图失败"));
    }

    // 参数验证
    if (!Array.isArray(polylineOptions)) {
      const error = new TypeError("参数必须是折线配置数组");
      console.warn("Polyline模块: 参数验证失败", error);
      return Promise.reject(error);
    }

    // 验证数组不为空
    if (polylineOptions.length === 0) {
      return Promise.reject(new TypeError("Polyline模块: 折线配置数组为空"));
    }

    this.extra = extra;

    try {
      // 加载动画插件
      await this.loadMoveAnimationPlugin();

      // 清除现有折线
      if (this.polylineInstances) {
        this.removePolylines();
      }

      // 创建所有折线实例
      this.polylineInstances = await this.createAllPolylines(polylineOptions);

      return {
        name: "Polyline",
        instance: this.polylineInstances,
        events: {
          remove: this.removePolylines.bind(this),
          closeInfoWindow: this.closeInfoWindow.bind(this)
        }
      };
    } catch (err) {
      console.error("加载折线动画插件失败:", err);
      return Promise.reject(new TypeError(`加载折线动画插件失败:${err}`));
    }
  },

  /**
   * 加载移动动画插件
   * @returns {Promise<void>}
   */
  loadMoveAnimationPlugin(): Promise<void> {
    return new Promise((resolve, reject) => {
      this.AMap.plugin("AMap.MoveAnimation", (err?: Error) => {
        if (err) reject(err);
        else resolve();
      });
    });
  },

  /**
   * 批量创建折线实例
   * @param {PolylineOptions[]} options - 折线配置数组
   * @returns {Promise<PolylineInstance[]>} 折线实例数组的Promise
   */
  async createAllPolylines(options: PolylineOptions[]): Promise<PolylineInstance[]> {
    // 分步处理：创建实例 -> 过滤无效值 -> 类型断言
    const polylineInstances = options
      .map(option => this.createSinglePolyline(option))
      // 使用类型守卫替代强制类型转换，确保类型安全
      .filter((instance): instance is PolylineInstance => Boolean(instance));

    return polylineInstances;
  },

  // #region 创建单条折线
  /**
   * 创建单条折线
   * @param {Object} option - 折线配置
   * @param {Array} option.path - 折线路径
   * @returns {Object|null} 折线实例
   */

  createSinglePolyline(option: PolylineOptions): PolylineInstance | null {
    // 完善的参数验证
    if (!option || !Array.isArray(option.path) || option.path.length === 0) {
      console.error("Invalid option: path must be a non-empty array");
      return null;
    }
    const AMap = this.AMap;
    const map = this.map;

    // 坐标转换
    let path = option.path;

    if (this.extra?.coordTransform && coordinateConverter[this.extra?.coordTransform]) {
      path = option.path.map(([lng, lat]) => {
        const [tLng, tLat] = coordinateConverter[this.extra?.coordTransform as string](lng, lat);
        return [tLng, tLat] as LngLat;
      });
    }

    // 创建起点、终点和行驶中的 marker
    const startMarker = this.createMarker(
      path[0] || [],
      this.extra?.icon?.StartPoint || { content: StartingPointSvg, offset: [-20, -40], zIndex: 100 }
    );
    const endMarker = this.createMarker(
      path[path.length - 1] || [],
      this.extra?.icon?.EndPoint || { content: EndPointSvg, offset: [-20, -40], zIndex: 100 }
    );

    const marker = this.createMarker(
      path[0] || [],
      this.extra?.icon?.Driving || { content: DrivingSvg, offset: [-9, -18], zIndex: 101 }
    );

    // 是否创建停留点
    const { stopoverMarkers, stopoverPositions } = this.createStopoverMarkers(option);

    // 创建经过位置点位
    this.createLabeledMarkers(path, option, {
      startMarker,
      endMarker,
      stopoverMarkers,
      stopoverPositions
    });

    // 创建围栏
    this.createFence(this.extra?.isFence);

    // 创建折线
    const polyline = new AMap.Polyline({
      ...option,
      map,
      path,
      cursor: "default"
    });

    // 创建已通过路径的折线
    const passedPolyline = new AMap.Polyline({
      strokeColor: option.strokeColor,
      showDir: option.showDir,
      strokeWeight: option.strokeWeight,
      strokeOpacity: option.strokeOpacity || 1, //线透明度
      strokeStyle: option.strokeStyle || "solid", //线样式
      map,
      cursor: "default"
    });

    // 创建实例对象并添加事件监听机制
    const instance: PolylineInstance = {
      polyline,
      passedPolyline,
      marker,
      methods: null,
      eventListeners: {
        // 目前只有折线进度事件
        percentChange: []
      },
      /**
       * 注册事件监听器
       * @param eventName 事件名称
       * @param callback 事件回调函数
       * @returns 实例本身，支持链式调用
       */
      on: function (eventName: string, callback: (percent: number, index: number) => void): void {
        if (typeof eventName !== "string" || typeof callback !== "function") {
          return;
        }

        if (!this.eventListeners[eventName]) {
          this.eventListeners[eventName] = [];
        }

        this.eventListeners[eventName].push(callback);
      },

      /**
       * 移除事件监听器
       * @param eventName 事件名称
       * @param callback 可选，指定要移除的回调函数
       * @returns 实例本身，支持链式调用
       */
      off: function (eventName: string, callback: (percent: number, index: number) => void): void {
        if (typeof eventName !== "string") {
          return;
        }

        if (!this.eventListeners[eventName]) {
          return;
        }

        if (typeof callback === "function") {
          // 移除特定的回调函数
          const index = this.eventListeners[eventName].indexOf(callback);
          if (index !== -1) {
            this.eventListeners[eventName].splice(index, 1);
          }
        } else {
          // 清空所有回调函数
          delete this.eventListeners[eventName];
        }
      }
    };

    // 绑定折线控制方法
    const methods = this.bindPolylineEvents({ marker, passedPolyline, instance }, path);
    instance.methods = methods;

    // 调整视图以适应路径
    this.map.setFitView(null, true);

    return instance;
  },
  // #endregion 创建单条折线

  // #region 创建起点终点围栏
  // 存储创建的围栏对象，便于管理和清理
  _fenceInstances: [] as any[],

  /**
   * 创建围栏
   * @param options 配置选项，如果未传入则使用默认配置
   * @returns 返回创建的围栏对象数组
   */
  createFence(options?: { fences?: any[]; isOn?: boolean }) {
    // 获取配置，使用传入参数或默认配置
    const fenceConfig = options || this.extra?.isFence;

    // 检查围栏功能是否启用
    if (!fenceConfig?.isOn) {
      return [];
    }

    // 检查围栏配置是否存在且非空
    const fenceList = fenceConfig.fences;
    if (!Array.isArray(fenceList) || fenceList.length === 0) {
      console.warn("围栏配置为空或无效，跳过创建");
      return [];
    }

    try {
      // 获取地图和API实例
      const AMap = this.AMap;
      const map = this.map;

      const fences: any[] = [];

      // 验证并创建每个围栏
      fenceList.forEach((fenceConfig, index) => {
        if (!fenceConfig || typeof fenceConfig !== "object") {
          console.warn(`第${index + 1}个围栏配置无效，跳过`);
          return;
        }

        try {
          // 对围栏中心点添加文本说明
          const text = new AMap.Text({
            text: fenceConfig.text || "",
            anchor: "center", // 设置文本标记锚点
            draggable: false,
            style: fenceConfig.textStyle || {
              "background-color": "white",
              "border-width": 0,
              "text-align": "center",
              "font-size": "12px"
            },
            position: fenceConfig.center || []
          });

          text.setMap(map);
          // 确保围栏被添加到地图
          const fence = new AMap.Circle({ ...fenceConfig });
          fences.push(fence);
        } catch (error) {
          console.error(`创建第${index + 1}个围栏失败:`, error);
        }
      });

      // 存储围栏实例，便于后续管理
      if (fences.length > 0) {
        this._fenceInstances.push(...fences);
        console.log(`成功创建${fences.length}个围栏`);
      }

      map.add(fences);
      return fences;
    } catch (error) {
      console.error("创建围栏时发生错误:", error);
      return [];
    }
  },

  /**
   * 清理所有围栏
   * @description 移除地图上的所有围栏并清理实例数组
   */
  removeFences(): void {
    if (!this.map || !this._fenceInstances.length) {
      return;
    }

    // 从地图上移除所有围栏
    this._fenceInstances.forEach(fence => {
      if (fence && typeof fence.remove === "function") {
        fence.remove();
      }
    });

    // 清理围栏实例数组
    this._fenceInstances = [];
  },

  // #endregion 创建起点终点围栏

  // #region 创建 marker 的公共函数
  createMarker(position: LngLat, params: PointIcon) {
    return new this.AMap.Marker({
      map: this.map,
      position,
      content: params.content || "",
      offset: params.offset ? new this.AMap.Pixel(params.offset[0], params.offset[1]) : [0, 0],
      zIndex: params.zIndex || 4,
      icon: params.icon,
      cursor: "default"
    });
  },
  // #endregion 创建 marker 的公共函数

  // #region 创建停留点
  createStopoverMarkers(option: PolylineOptions) {
    // 是否创建停留点
    let stopoverMarkers = <any[]>[]; // 停留点标记
    let stopoverPositions = <LngLat[]>[]; // 停留点经纬度， 转换后的坐标用于与path对比
    if (this.extra?.isStopovers && option.extra?.stopovers && option.extra?.stopovers.length > 0) {
      stopoverPositions = option.extra.stopovers;
      if (this.extra?.coordTransform && coordinateConverter[this.extra?.coordTransform]) {
        stopoverPositions = option.extra.stopovers.map(([lng, lat]) => {
          const [tLng, tLat] = coordinateConverter[this.extra?.coordTransform as string](lng, lat);
          return [tLng, tLat] as LngLat;
        });
      }

      stopoverMarkers = stopoverPositions.map(item => {
        return this.createMarker(item, this.extra?.icon?.StopoverPoint || { content: StopoverPointSvg, offset: [-15, -30] });
      });
    }
    return { stopoverMarkers, stopoverPositions };
  },

  //  #endregion 创建停留点

  // #region 创建 海量点 的经过位置点位
  /**
   * 创建经过位置点位
   * @param {Array} path - 折线路径坐标
   * @param {Object} option - 折线配置选项
   * @param {Object} markers - 标记点对象，包含起点、终点、停留点标记和停留点位置
   */
  createLabeledMarkers(
    path: LngLat[],
    option: PolylineOptions,
    markers: {
      startMarker: any;
      endMarker: any;
      stopoverMarkers: any[];
      stopoverPositions: LngLat[];
    }
  ) {
    // 是否创建经过位置点位
    if (!this.extra?.isLabeled) {
      return;
    }

    const { startMarker, endMarker, stopoverMarkers, stopoverPositions } = markers;

    // 初始化区域监控所需的数据结构
    this.initRegionMonitoring();

    const labeledPosition: LabeledPosition[] = []; // 标注点位
    const seen = new Set();
    for (const i in path) {
      // 将坐标转换为字符串作为Set的键
      const key = path[i].join(",");
      if (!seen.has(key)) {
        seen.add(key);
        labeledPosition.push({
          lnglat: path[i],
          content: option?.extra?.origin ? option.extra.origin[i] : {},
          index: parseInt(i) // 保存原始索引用于区域分组
        });
      }
    }

    if (!labeledPosition.length) {
      return;
    }

    // 单独给起点终点创建标注
    this.bindMarkerEvents(
      startMarker,
      option?.extra?.infoWindowOpts,
      labeledPosition[0].content || "",
      labeledPosition[0].lnglat
    );
    this.bindMarkerEvents(
      endMarker,
      option?.extra?.infoWindowOpts,
      labeledPosition[labeledPosition.length - 1].content || "",
      labeledPosition[labeledPosition.length - 1].lnglat
    );

    // 处理停留点和准备海量点数据
    const nonStopoverPoints: LabeledPosition[] = [];
    const stopoverData = new Map(); // 用于快速查找停留点

    // 先将所有停留点存入Map
    stopoverPositions.forEach((stopover, index) => {
      const key = stopover.join(",");
      stopoverData.set(key, { index, stopover });
    });

    // 分离停留点和非停留点
    labeledPosition.forEach((item, index) => {
      if (index !== 0 && index !== labeledPosition.length - 1) {
        const key = item.lnglat.join(",");
        const stopoverInfo = stopoverData.get(key);
        if (stopoverInfo) {
          // 是停留点，绑定事件
          this.bindMarkerEvents(
            stopoverMarkers[stopoverInfo.index],
            option?.extra?.infoWindowOpts,
            item.content || "",
            item.lnglat
          );
        } else {
          // 非停留点，加入海量点数据
          nonStopoverPoints.push(item);
        }
      }
    });

    // 创建基于区域的海量点监控
    this.createMassPointRegionMonitors(nonStopoverPoints, option);
  },

  /**
   * 初始化区域监控数据结构
   */
  regionData: null as null | Record<string, LabeledPosition[]>, // 按区域存储点数据
  regionPolygons: null as null | any[], // 存储监控区域多边形
  activeMassMarkers: null as null | Record<string, any>, // 存储当前活动的海量点实例
  regionPointCache: null as null | Map<string, LabeledPosition[]>, // 缓存区域内的点数据
  tempMassMarker: null as any, // 临时海量点实例，用于批量创建和删除

  initRegionMonitoring() {
    // 清除之前可能存在的数据
    this.cleanupRegionMonitors();

    // 初始化数据结构
    this.regionData = {} as Record<string, LabeledPosition[]>; // 按区域存储点数据
    this.regionPolygons = [] as any[]; // 存储监控区域多边形
    this.activeMassMarkers = {} as Record<string, any>; // 存储当前活动的海量点实例
    this.regionPointCache = new Map(); // 缓存区域内的点数据
  },

  /**
   * 创建基于区域的海量点监控器
   * 按空间区域划分点数据，实现鼠标移入区域时渲染该区域的海量点
   * 鼠标离开区域时移除海量点
   * @param points - 标注点位数组
   * @param option - 折线配置选项
   */
  createMassPointRegionMonitors(points: LabeledPosition[], option: PolylineOptions) {
    if (!points.length) return;

    // 计算合适的区域大小（根据点数动态调整）
    const regionSize = Math.max(10, Math.ceil(points.length / 100)); // 合理的区域大小

    const spatialGroups = this.spatiallyGroupPoints(points, regionSize);

    // 为每个空间组创建监控区域
    spatialGroups.forEach((group, groupIndex) => {
      const regionKey = `region_${groupIndex}`;
      this.regionData && (this.regionData[regionKey] = group);

      // 创建监控区域多边形
      const polygon = this.createMonitorPolygon(group.map(p => p.lnglat));
      if (!polygon) return;

      polygon.regionKey = regionKey; // 保存区域标识
      this.regionPolygons && this.regionPolygons.push(polygon);

      // 鼠标移入事件 - 创建并显示该区域的海量点
      polygon.on("mouseover", () => {
        this.showRegionMassPoints(regionKey, group, option);
      });

      // 鼠标移出事件 - 移除该区域的海量点
      polygon.on("mouseout", () => {
        // 隐藏当前区域的海量点
        this.hideRegionMassPoints(regionKey);
      });
    });
  },

  /**
   * 空间分组点数据
   * 按照经纬度范围和点数进行分组
   * @param points - 标注点位数组
   * @param maxPointsPerRegion - 每个区域最大点数
   * @returns 分组后的数组
   */
  spatiallyGroupPoints(points: LabeledPosition[], maxPointsPerRegion: number) {
    if (!points.length || maxPointsPerRegion <= 0) return [];

    const groups: LabeledPosition[][] = [];
    let currentGroup: LabeledPosition[] = [];

    // 按原始顺序分组（保持轨迹连贯性）
    points
      .sort((a, b) => a.index - b.index)
      .forEach(point => {
        if (currentGroup.length >= maxPointsPerRegion) {
          groups.push([...currentGroup]);
          currentGroup = [];
        }
        currentGroup.push(point);
      });

    // 添加最后一组
    if (currentGroup.length > 0) {
      groups.push(currentGroup);
    }

    return groups;
  },

  /**
   * 显示指定区域的海量点
   * 当鼠标移入监控区域时调用此方法，创建并显示该区域的海量点
   * @param regionKey - 区域标识
   * @param points - 该区域内的标注点数组
   * @param option - 折线配置选项
   */

  showRegionMassPoints(regionKey: string, points: LabeledPosition[], option: PolylineOptions) {
    // 如果该区域已经有活动的海量点，则不重复创建
    if (this.activeMassMarkers && this.activeMassMarkers[regionKey]) {
      return;
    }

    // 从缓存获取或创建海量点数据
    let massData: any;
    if (this.regionPointCache && this.regionPointCache.has(regionKey)) {
      massData = this.regionPointCache.get(regionKey);
    } else {
      // 准备海量点数据
      massData = points.map(item => ({
        lnglat: item.lnglat,
        content: item.content
      }));
      this.regionPointCache && this.regionPointCache.set(regionKey, massData);
    }

    // 创建海量点实例
    const mass = new this.AMap.MassMarks(massData, {
      opacity: 0.9,
      zIndex: 120,
      cursor: "default",
      style: this.extra?.icon?.PointPng || {
        url: PointPng,
        anchor: new this.AMap.Pixel(10, 10),
        size: new this.AMap.Size(20, 20),
        zIndex: 4
      }
    });

    // 绑定鼠标交互事件
    mass.on("mouseover", (e: any) => {
      // 使用单一标记点显示信息窗口，避免创建多个标记
      if (!this.tempMassMarker) {
        this.tempMassMarker = this.createMarker([0, 0], this.extra?.icon?.PointSvg || { content: PointSvg, offset: [-10, -10] });
      }
      this.tempMassMarker.setPosition(e.data.lnglat);
      this.bindMarkerEvents(this.tempMassMarker, option?.extra?.infoWindowOpts, e.data.content || "", e.data.lnglat);
    });

    // 设置地图并存储实例
    mass.setMap(this.map);
    this.activeMassMarkers && (this.activeMassMarkers[regionKey] = mass);
  },

  /**
   * 隐藏指定区域的海量点
   * 当鼠标离开监控区域时调用此方法
   * @param regionKey - 区域标识
   */
  hideRegionMassPoints(regionKey: string) {
    const mass = this.activeMassMarkers && this.activeMassMarkers[regionKey];
    if (mass) {
      mass.setMap(null);
      this.activeMassMarkers && delete this.activeMassMarkers[regionKey];
    }
  },

  /**
   * 创建监控多边形
   * 创建一个包围轨迹线的监控区域，用于捕获鼠标事件
   * @param points - 轨迹线的经纬度点数组
   * @returns 监控区域多边形实例
   */
  createMonitorPolygon(points: LngLat[]) {
    if (!points || points.length === 0) return null;

    // 计算点集的边界
    let minLng = points[0][0],
      maxLng = points[0][0];
    let minLat = points[0][1],
      maxLat = points[0][1];

    points.forEach(([lng, lat]) => {
      minLng = Math.min(minLng, lng);
      maxLng = Math.max(maxLng, lng);
      minLat = Math.min(minLat, lat);
      maxLat = Math.max(maxLat, lat);
    });

    // 添加适当的缓冲区，使监控区域更容易被触发
    const lngRange = maxLng - minLng;
    const latRange = maxLat - minLat;
    const buffer = Math.max(0.000005, Math.max(lngRange, latRange) * 0.01);

    minLng -= buffer;
    maxLng += buffer;
    minLat -= buffer;
    maxLat += buffer;

    // 创建矩形多边形
    return new this.AMap.Polygon({
      path: [
        [minLng, minLat],
        [maxLng, minLat],
        [maxLng, maxLat],
        [minLng, maxLat]
      ],
      strokeOpacity: 0,
      fillOpacity: 0.01, // 几乎透明但可交互
      map: this.map,
      zIndex: 120,
      // 设置事件穿透和阻止事件冒泡，确保不会与轨迹线的事件冲突
      draggable: false,
      cursor: "default"
    });
  },

  /**
   * 清理区域监控资源
   */
  cleanupRegionMonitors() {
    // 清理临时标记点
    if (this.tempMassMarker && this.tempMassMarker.setMap) {
      this.tempMassMarker.setMap(null);
      this.tempMassMarker = null;
    }

    // 清理活动的海量点实例
    if (this.activeMassMarkers) {
      Object.values(this.activeMassMarkers).forEach(mass => {
        if (mass && mass.setMap) {
          mass.setMap(null);
        }
      });
      this.activeMassMarkers = null;
    }

    // 清理监控区域多边形
    if (this.regionPolygons) {
      this.regionPolygons.forEach(region => {
        if (region && region.setMap) {
          region.setMap(null);
        }
      });
      this.regionPolygons = null;
    }

    // 清理缓存和数据
    this.regionData = {};
    if (this.regionPointCache) {
      this.regionPointCache.clear();
      this.regionPointCache = null;
    }
  },

  // #endregion 创建 海量点 的经过位置点位

  // #region 绑定标记点弹窗
  /**
   * 绑定标记点交互事件
   * @param {AMap.Marker} marker - AMap标记点实例
   * @param {Object} [opts] - 信息窗口配置
   * @param {Object} [text] - 标记点文本信息
   * @param {Array} position - 标记点位置坐标
   */
  infoWindow: null as any,
  bindMarkerEvents(marker: any, opts: InfoWindowOptions, text: any, position: LngLat) {
    // 检查是否需要解除信息窗口
    if (this.extra?.relieveInfoWindow) return;

    // 参数验证
    if (!marker || !position) {
      console.error("Invalid parameters: marker and position are required");
      return;
    }

    // 绑定点击事件
    marker.on("click", () => {
      // 避免重复创建信息窗口
      if (this.infoWindow) {
        this.closeInfoWindow();
      }

      // 只有当 opts 存在且有 content 方法时才创建信息窗口
      if (opts && typeof opts.content === "function") {
        this.infoWindow = new this.AMap.InfoWindow({
          ...opts,
          position,
          content: opts.content({ text, position }),
          offset: opts.offset || [0, -30],
          autoMove: opts.autoMove || false
        });

        this.infoWindow.open(this.map, position);
      }
    });
  },
  // #endregion 绑定标记点弹窗

  // #region 关闭信息窗口
  /**
   * 关闭当前打开的信息窗口
   */
  closeInfoWindow() {
    if (this.infoWindow) {
      this.infoWindow.close();
      this.infoWindow = null;
    }
  },
  // #endregion 关闭信息窗口

  // #region 绑定折线控制事件
  /**
   * 绑定折线动画控制事件
   * @param instance 折线实例，仅包含marker和passedPolyline属性
   * @param path 折线路径坐标数组
   * @returns 动画控制方法对象
   */
  bindPolylineEvents(
    { marker, passedPolyline, instance }: { marker: any; passedPolyline: any; instance: PolylineInstance },
    path: LngLat[]
  ): PolylineMethods {
    let timer: any = null; // 定时器控制行进的进度
    let percentIdx = 0; // 记录当前路径索引

    // 验证路径是否有效
    if (!Array.isArray(path) || path.length === 0) {
      console.error("无效的路径参数: 必须是非空数组");
      return {
        start: () => console.warn("空动画控制器: start方法未执行"),
        pause: () => console.warn("空动画控制器: pause方法未执行"),
        resume: () => console.warn("空动画控制器: resume方法未执行"),
        stop: () => console.warn("空动画控制器: stop方法未执行")
      };
    }

    // 标记点移动事件
    marker.on("moving", (e: any) => {
      passedPolyline.setPath(e.passedPath);

      const currentIdx = checkAnimationProgress();
      // 计算行驶进度
      const percent = path.length > 2 ? (currentIdx / (path.length - 1)) * 100 : 0;

      console.log(percent, "percent");
      // 触发percentChange事件
      instance.eventListeners.percentChange.forEach(callback => {
        callback(percent, currentIdx);
      });
    });

    // 同步检查当前实际的动画位置
    const checkAnimationProgress = () => {
      const currentPos = marker.getPosition();
      if (!currentPos || !path.length) return percentIdx;

      // 查找与当前点位置最接近的路径点（完全基于实际位置，不受percentIdx影响）
      let closestIndex = 0;
      let minDistance = Infinity;

      for (let i = 0; i < path.length; i++) {
        const [lng, lat] = path[i];
        // 标准的 欧几里得距离公式 ，用于计算两个地理坐标点之间的直线距离。
        const distance = Math.sqrt(Math.pow(currentPos.lng - lng, 2) + Math.pow(currentPos.lat - lat, 2));
        if (distance < minDistance) {
          minDistance = distance;
          closestIndex = i;
        }
      }

      return closestIndex;
    };

    /** 清除定时器 */
    const clearTimer = (): void => {
      if (timer) {
        clearInterval(timer);
        timer = null;
      }
    };

    /** 设置定时器 */
    const setupTimer = (duration: number): void => {
      clearTimer();

      timer = setInterval(() => {
        // 检查实际的动画进度（基于真实位置，不受定时器推进影响）
        const currentIdx = checkAnimationProgress();
        percentIdx = currentIdx;

        // 只有当动画真正到达或接近末尾位置时才停止定时器
        if (currentIdx >= path.length - 1) {
          clearTimer();
        }
      }, duration);
    };

    /**
     * 开始动画
     * @param duration 动画持续时间(毫秒)
     * @param opts 动画配置项
     */
    const start: AnimationEvent = (duration = 1000, opts = {}) => {
      // 设置最小步长时间为 50ms，避免定时器过于频繁
      const stepTime = Math.max(50, duration);

      passedPolyline.show();

      percentIdx = 0;
      setupTimer(stepTime);

      marker.moveAlong(path, {
        ...opts,
        duration: stepTime
      });
    };

    /** 暂停动画 */
    const pause = (): void => {
      marker.pauseMove();
      clearTimer();
    };

    /**
     * 恢复动画
     * @param duration 动画持续时间(毫秒)
     * @param opts 动画配置项
     */
    const resume: AnimationEvent = (duration = 1000, opts = {}) => {
      // 设置最小步长时间为 50ms，避免定时器过于频繁
      const stepTime = Math.max(50, duration);
      setupTimer(stepTime);
      // 在恢复前同步实际位置
      percentIdx = checkAnimationProgress();

      const newPath = path.slice(percentIdx);
      marker.moveAlong(newPath, {
        ...opts,
        duration: stepTime
      });
    };

    /** 停止动画并重置状态 */
    const stop = (): void => {
      passedPolyline.hide();
      marker.setPosition(path[0]);
      marker.stopMove();
      clearTimer();
      percentIdx = 0;
    };

    return { start, pause, resume, stop };
  },

  // #endregion 绑定折线控制事件

  /**
   * 移除所有折线
   * @description 清除地图上所有折线覆盖物并清理实例数组
   */
  removePolylines(): void {
    if (!this.map) {
      console.warn("Map instance is not initialized, cannot remove polylines");
      return;
    }

    // 先清理所有围栏
    this.removeFences();

    // 清除地图上的所有覆盖物
    this.map.clearMap();

    // 清理polylineInstances数组并停止所有标记移动
    if (this.polylineInstances) {
      this.polylineInstances.forEach(item => {
        item.marker.stopMove();
      });
      this.polylineInstances = [];
    }

    // 清理区域监控资源
    this.cleanupRegionMonitors();
  }
};
